In [1]:
import tensorflow as tf
from tensorflow.keras import models, layers
import matplotlib.pyplot as plt
In [2]:
BATCH_SIZE = 32
IMAGE_SIZE = 256
CHANNELS=3
EPOCHS=50
In [3]:
dataset = tf.keras.preprocessing.image_dataset_from_directory(
    "PlantVillage",
    seed=123,
    shuffle=True,
    image_size=(IMAGE_SIZE,IMAGE_SIZE),
    batch_size=BATCH_SIZE
)
Found 2152 files belonging to 3 classes.
In [4]:
class_names = dataset.class_names
class_names
Out[4]:
['Potato___Early_blight', 'Potato___Late_blight', 'Potato___healthy']
In [5]:
len(dataset)
Out[5]:
68
In [6]:
for image_batch, labels_batch in dataset.take(1):
    print(image_batch.shape)
    print(labels_batch.numpy())
(32, 256, 256, 3)
[1 1 1 0 0 0 0 0 1 1 1 1 0 1 0 1 1 1 0 1 0 1 0 0 1 0 0 1 1 2 0 0]
In [7]:
plt.figure(figsize=(10, 10))
for image_batch, labels_batch in dataset.take(1):
    for i in range(12):
        ax = plt.subplot(3, 4, i + 1)
        plt.imshow(image_batch[i].numpy().astype("uint8"))
        plt.title(class_names[labels_batch[i]])
        plt.axis("off")
No description has been provided for this image
In [8]:
len(dataset)
Out[8]:
68
In [9]:
train_size = 0.8
len(dataset)*train_size
Out[9]:
54.400000000000006
In [10]:
train_ds = dataset.take(54)
len(train_ds)
Out[10]:
54
In [11]:
test_ds = dataset.skip(54)
len(test_ds)
Out[11]:
14
In [12]:
val_size=0.1
len(dataset)*val_size
Out[12]:
6.800000000000001
In [13]:
val_ds = test_ds.take(6)
len(val_ds)
Out[13]:
6
In [14]:
test_ds = test_ds.skip(6)
len(test_ds)
Out[14]:
8
In [15]:
def get_dataset_partitions_tf(ds, train_split=0.8, val_split=0.1, test_split=0.1, shuffle=True, shuffle_size=10000):
    assert (train_split + test_split + val_split) == 1
    
    ds_size = len(ds)
    
    if shuffle:
        ds = ds.shuffle(shuffle_size, seed=12)
    
    train_size = int(train_split * ds_size)
    val_size = int(val_split * ds_size)
    
    train_ds = ds.take(train_size)    
    val_ds = ds.skip(train_size).take(val_size)
    test_ds = ds.skip(train_size).skip(val_size)
    
    return train_ds, val_ds, test_ds
In [16]:
train_ds, val_ds, test_ds = get_dataset_partitions_tf(dataset)
In [17]:
len(train_ds)
Out[17]:
54
In [18]:
len(val_ds)
Out[18]:
6
In [19]:
len(test_ds)
Out[19]:
8
In [20]:
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
val_ds = val_ds.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
test_ds = test_ds.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
In [21]:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
In [22]:
IMAGE_SIZE = 256  # Change this to your desired image size

resize_and_rescale = keras.Sequential([
    layers.Resizing(IMAGE_SIZE, IMAGE_SIZE),  # No "experimental.preprocessing"
    layers.Rescaling(1./255),
])
In [23]:
print(tf.__version__)
2.18.0
In [24]:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

IMAGE_SIZE = 224  # Adjust as needed

resize_and_rescale = keras.Sequential([
    layers.Resizing(IMAGE_SIZE, IMAGE_SIZE),  # Correct usage
    layers.Rescaling(1./255),  # Correct usage
])
In [25]:
data_augmentation = keras.Sequential([
    layers.RandomFlip("horizontal_and_vertical"),  # Corrected
    layers.RandomRotation(0.2),  # Corrected
])
In [26]:
train_ds = train_ds.map(
    lambda x, y: (data_augmentation(x, training=True), y)
).prefetch(buffer_size=tf.data.AUTOTUNE)
In [27]:
input_shape = (BATCH_SIZE, IMAGE_SIZE, IMAGE_SIZE, CHANNELS)
n_classes = 3

model = models.Sequential([
    resize_and_rescale,
    layers.Conv2D(32, kernel_size = (3,3), activation='relu', input_shape=input_shape),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64,  kernel_size = (3,3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64,  kernel_size = (3,3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Flatten(),
    layers.Dense(64, activation='relu'),
    layers.Dense(n_classes, activation='softmax'),
])
C:\Users\Shravani\anaconda3\SHRAVANI 01\Lib\site-packages\keras\src\layers\convolutional\base_conv.py:107: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.
  super().__init__(activity_regularizer=activity_regularizer, **kwargs)
In [28]:
model.build(input_shape=input_shape)
In [29]:
model.summary()
Model: "sequential_3"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ Layer (type)                         ┃ Output Shape                ┃         Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ sequential_1 (Sequential)            │ (32, 224, 224, 3)           │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d (Conv2D)                      │ (32, 222, 222, 32)          │             896 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d (MaxPooling2D)         │ (32, 111, 111, 32)          │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_1 (Conv2D)                    │ (32, 109, 109, 64)          │          18,496 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_1 (MaxPooling2D)       │ (32, 54, 54, 64)            │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_2 (Conv2D)                    │ (32, 52, 52, 64)            │          36,928 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_2 (MaxPooling2D)       │ (32, 26, 26, 64)            │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_3 (Conv2D)                    │ (32, 24, 24, 64)            │          36,928 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_3 (MaxPooling2D)       │ (32, 12, 12, 64)            │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_4 (Conv2D)                    │ (32, 10, 10, 64)            │          36,928 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_4 (MaxPooling2D)       │ (32, 5, 5, 64)              │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ conv2d_5 (Conv2D)                    │ (32, 3, 3, 64)              │          36,928 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ max_pooling2d_5 (MaxPooling2D)       │ (32, 1, 1, 64)              │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ flatten (Flatten)                    │ (32, 64)                    │               0 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ dense (Dense)                        │ (32, 64)                    │           4,160 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ dense_1 (Dense)                      │ (32, 3)                     │             195 │
└──────────────────────────────────────┴─────────────────────────────┴─────────────────┘
 Total params: 171,459 (669.76 KB)
 Trainable params: 171,459 (669.76 KB)
 Non-trainable params: 0 (0.00 B)
In [30]:
model.compile(
    optimizer='adam',
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
    metrics=['accuracy']
)
In [31]:
history = model.fit(
    train_ds,
    batch_size=BATCH_SIZE,
    validation_data=val_ds,
    verbose=1,
    epochs=50,
)
Epoch 1/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 81s 1s/step - accuracy: 0.4803 - loss: 0.9428 - val_accuracy: 0.4375 - val_loss: 0.8926
Epoch 2/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 70s 1s/step - accuracy: 0.5227 - loss: 0.8748 - val_accuracy: 0.7292 - val_loss: 0.6152
Epoch 3/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 71s 1s/step - accuracy: 0.7511 - loss: 0.6128 - val_accuracy: 0.6354 - val_loss: 0.7688
Epoch 4/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 71s 1s/step - accuracy: 0.8048 - loss: 0.5317 - val_accuracy: 0.8177 - val_loss: 0.4932
Epoch 5/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 70s 1s/step - accuracy: 0.7905 - loss: 0.5145 - val_accuracy: 0.8177 - val_loss: 0.4321
Epoch 6/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.8424 - loss: 0.3795 - val_accuracy: 0.7865 - val_loss: 0.4805
Epoch 7/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.8375 - loss: 0.3972 - val_accuracy: 0.8802 - val_loss: 0.3073
Epoch 8/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 70s 1s/step - accuracy: 0.8710 - loss: 0.3198 - val_accuracy: 0.9010 - val_loss: 0.2190
Epoch 9/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9134 - loss: 0.2114 - val_accuracy: 0.8958 - val_loss: 0.2537
Epoch 10/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 82s 1s/step - accuracy: 0.9435 - loss: 0.1567 - val_accuracy: 0.9583 - val_loss: 0.1455
Epoch 11/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 84s 1s/step - accuracy: 0.9584 - loss: 0.1159 - val_accuracy: 0.8698 - val_loss: 0.3473
Epoch 12/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9154 - loss: 0.2271 - val_accuracy: 0.9375 - val_loss: 0.1428
Epoch 13/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 83s 1s/step - accuracy: 0.9752 - loss: 0.0701 - val_accuracy: 0.9792 - val_loss: 0.0969
Epoch 14/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 70s 1s/step - accuracy: 0.9774 - loss: 0.0735 - val_accuracy: 0.9792 - val_loss: 0.0658
Epoch 15/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9767 - loss: 0.0735 - val_accuracy: 0.9271 - val_loss: 0.2017
Epoch 16/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 82s 1s/step - accuracy: 0.9699 - loss: 0.0833 - val_accuracy: 0.9635 - val_loss: 0.1222
Epoch 17/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 82s 1s/step - accuracy: 0.9677 - loss: 0.0952 - val_accuracy: 0.9531 - val_loss: 0.1249
Epoch 18/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 82s 1s/step - accuracy: 0.9806 - loss: 0.0551 - val_accuracy: 0.9740 - val_loss: 0.0709
Epoch 19/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 70s 1s/step - accuracy: 0.9850 - loss: 0.0403 - val_accuracy: 0.9896 - val_loss: 0.0311
Epoch 20/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 70s 1s/step - accuracy: 0.9861 - loss: 0.0413 - val_accuracy: 0.9844 - val_loss: 0.0708
Epoch 21/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 82s 1s/step - accuracy: 0.9688 - loss: 0.0804 - val_accuracy: 0.9583 - val_loss: 0.1019
Epoch 22/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9824 - loss: 0.0527 - val_accuracy: 0.9844 - val_loss: 0.0591
Epoch 23/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9796 - loss: 0.0755 - val_accuracy: 0.9896 - val_loss: 0.0348
Epoch 24/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 83s 1s/step - accuracy: 0.9800 - loss: 0.0606 - val_accuracy: 0.9844 - val_loss: 0.0410
Epoch 25/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9892 - loss: 0.0395 - val_accuracy: 0.9896 - val_loss: 0.0271
Epoch 26/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9927 - loss: 0.0272 - val_accuracy: 0.9792 - val_loss: 0.0393
Epoch 27/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9807 - loss: 0.0444 - val_accuracy: 0.9844 - val_loss: 0.0444
Epoch 28/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 83s 1s/step - accuracy: 0.9880 - loss: 0.0296 - val_accuracy: 0.9948 - val_loss: 0.0140
Epoch 29/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9812 - loss: 0.0619 - val_accuracy: 0.9219 - val_loss: 0.1288
Epoch 30/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9828 - loss: 0.0475 - val_accuracy: 0.9948 - val_loss: 0.0231
Epoch 31/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 83s 1s/step - accuracy: 0.9845 - loss: 0.0345 - val_accuracy: 0.9896 - val_loss: 0.0241
Epoch 32/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 82s 1s/step - accuracy: 0.9954 - loss: 0.0173 - val_accuracy: 0.9688 - val_loss: 0.0833
Epoch 33/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9804 - loss: 0.0632 - val_accuracy: 0.9844 - val_loss: 0.0380
Epoch 34/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 83s 1s/step - accuracy: 0.9815 - loss: 0.0463 - val_accuracy: 0.9948 - val_loss: 0.0266
Epoch 35/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9877 - loss: 0.0406 - val_accuracy: 1.0000 - val_loss: 0.0193
Epoch 36/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9925 - loss: 0.0253 - val_accuracy: 0.9844 - val_loss: 0.0309
Epoch 37/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 70s 1s/step - accuracy: 0.9903 - loss: 0.0211 - val_accuracy: 0.9167 - val_loss: 0.2392
Epoch 38/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 70s 1s/step - accuracy: 0.9819 - loss: 0.0488 - val_accuracy: 0.9844 - val_loss: 0.0400
Epoch 39/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 82s 1s/step - accuracy: 0.9939 - loss: 0.0184 - val_accuracy: 0.9792 - val_loss: 0.0778
Epoch 40/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9912 - loss: 0.0268 - val_accuracy: 0.9896 - val_loss: 0.0302
Epoch 41/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9931 - loss: 0.0162 - val_accuracy: 0.9948 - val_loss: 0.0095
Epoch 42/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 70s 1s/step - accuracy: 0.9866 - loss: 0.0401 - val_accuracy: 1.0000 - val_loss: 0.0049
Epoch 43/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9897 - loss: 0.0293 - val_accuracy: 0.9948 - val_loss: 0.0100
Epoch 44/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 69s 1s/step - accuracy: 0.9984 - loss: 0.0097 - val_accuracy: 0.9844 - val_loss: 0.0423
Epoch 45/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 83s 1s/step - accuracy: 0.9902 - loss: 0.0242 - val_accuracy: 0.9792 - val_loss: 0.0714
Epoch 46/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 71s 1s/step - accuracy: 0.9930 - loss: 0.0173 - val_accuracy: 0.9844 - val_loss: 0.0276
Epoch 47/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 70s 1s/step - accuracy: 0.9941 - loss: 0.0205 - val_accuracy: 0.9792 - val_loss: 0.0497
Epoch 48/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 71s 1s/step - accuracy: 0.9843 - loss: 0.0551 - val_accuracy: 0.9844 - val_loss: 0.0322
Epoch 49/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 72s 1s/step - accuracy: 0.9964 - loss: 0.0135 - val_accuracy: 0.9792 - val_loss: 0.0419
Epoch 50/50
54/54 ━━━━━━━━━━━━━━━━━━━━ 71s 1s/step - accuracy: 0.9816 - loss: 0.0531 - val_accuracy: 0.9323 - val_loss: 0.1460
In [50]:
scores = model.evaluate(test_ds)
8/8 ━━━━━━━━━━━━━━━━━━━━ 3s 320ms/step - accuracy: 0.9499 - loss: 0.1632
In [51]:
scores
Out[51]:
[0.165579155087471, 0.953125]
In [52]:
history
Out[52]:
<keras.src.callbacks.history.History at 0x1aad2f75130>
In [53]:
history.params
Out[53]:
{'verbose': 1, 'epochs': 50, 'steps': 54}
In [54]:
history.history.keys()
Out[54]:
dict_keys(['accuracy', 'loss', 'val_accuracy', 'val_loss'])
In [55]:
type(history.history['loss'])
Out[55]:
list
In [56]:
len(history.history['loss'])
Out[56]:
50
In [57]:
history.history['loss'][:5] # show loss for first 5 epochs
Out[57]:
[0.9157429933547974,
 0.8123927712440491,
 0.5875206589698792,
 0.5011534690856934,
 0.499131441116333]
In [58]:
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

loss = history.history['loss']
val_loss = history.history['val_loss']
In [59]:
plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.plot(range(EPOCHS), acc, label='Training Accuracy')
plt.plot(range(EPOCHS), val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
Out[59]:
Text(0.5, 1.0, 'Training and Validation Accuracy')
No description has been provided for this image
In [60]:
plt.subplot(1, 2, 2)
plt.plot(range(EPOCHS), loss, label='Training Loss')
plt.plot(range(EPOCHS), val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
No description has been provided for this image
In [61]:
#Run prediction on a sample image
In [62]:
import numpy as np
for images_batch, labels_batch in test_ds.take(1):
    
    first_image = images_batch[0].numpy().astype('uint8')
    first_label = labels_batch[0].numpy()
    
    print("first image to predict")
    plt.imshow(first_image)
    print("actual label:",class_names[first_label])
    
    batch_prediction = model.predict(images_batch)
    print("predicted label:",class_names[np.argmax(batch_prediction[0])])
first image to predict
actual label: Potato___Late_blight
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 383ms/step
predicted label: Potato___Late_blight
No description has been provided for this image
In [63]:
import numpy as np
for images_batch, labels_batch in test_ds.take(1):
    
    first_image = images_batch[0].numpy().astype('uint8')
    first_label = labels_batch[0].numpy()
    
    print("first image to predict")
    plt.imshow(first_image)
    print("actual label:",class_names[first_label])
    
    batch_prediction = model.predict(images_batch)
    print("predicted label:",class_names[np.argmax(batch_prediction[0])])
first image to predict
actual label: Potato___Early_blight
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 408ms/step
predicted label: Potato___Early_blight
No description has been provided for this image
In [64]:
def predict(model, img):
    img_array = tf.keras.preprocessing.image.img_to_array(images[i].numpy())
    img_array = tf.expand_dims(img_array, 0)

    predictions = model.predict(img_array)

    predicted_class = class_names[np.argmax(predictions[0])]
    confidence = round(100 * (np.max(predictions[0])), 2)
    return predicted_class, confidence
In [65]:
plt.figure(figsize=(15, 15))
for images, labels in test_ds.take(1):
    for i in range(9):
        ax = plt.subplot(3, 3, i + 1)
        plt.imshow(images[i].numpy().astype("uint8"))
        
        predicted_class, confidence = predict(model, images[i].numpy())
        actual_class = class_names[labels[i]] 
        
        plt.title(f"Actual: {actual_class},\n Predicted: {predicted_class}.\n Confidence: {confidence}%")
        
        plt.axis("off")
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 103ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 95ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 93ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 127ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 112ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 89ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 120ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 111ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 87ms/step
No description has been provided for this image
In [66]:
import os

models_dir = "../models"

# Ensure the directory exists
os.makedirs(models_dir, exist_ok=True)

# Get the highest existing model version
model_version = max([int(i) for i in os.listdir(models_dir) if i.isdigit()] + [0]) + 1

# Save the model with a valid extension
model.save(f"{models_dir}/{model_version}.keras") 
In [67]:
model.save("../potatoes.keras") 
In [ ]: